security(hooks): fix the two critical v0.22.1 re-audit findings (CR-01, CR-02) + honest positioning (ME-24)#85
Merged
Conversation
…t mode; qualified enforcement claims (CR-01, CR-02, ME-24) - secret-redact.mjs redacts recursively while preserving the tool_response's exact structure, so Claude Code no longer discards the replacement for structured built-in outputs and keeps the unredacted original. - secret-redact.sh propagates the redactor's exit status instead of an unconditional exit 0, so FORGE_GUARD_STRICT=1 degradation (exit 2) actually reaches Claude. Comments/docs now state PostToolUse cannot block — exit 2 is surfaced stderr feedback; blocking belongs to the PreToolUse guard. - Tests: Bash/Grep-shaped structured responses keep object shape, clean structured response emits nothing, wrapper-level strict tests drive the real secret-redact.sh. - README/GUIDE wording: hooks are Claude Code-specific and advisory by default; guardrails are defence in depth, not a sandbox. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01KfCEnSJzSG914yyVesjjD6
CodeWithJuber
marked this pull request as ready for review
July 19, 2026 05:38
Contributor
|
Docs PR opened: #86 Added a July 19 changelog entry covering the secret-redactor structured-output fix, strict-mode exit propagation, and clearer hook positioning. |
This was referenced Jul 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
The v0.22.1 edge-case re-audit found two critical defects in the secret-redaction guard, plus remaining enforcement overclaims in the docs. This PR fixes exactly that scope.
CR-01 — PostToolUse redaction violated the structured-output contract. Built-in tools (Bash, Read, Grep, …) return structured objects, and Claude Code ignores an
updatedToolOutputwhose shape doesn't match the original — the redactor stringified objects, so its replacement was silently discarded and the unredacted, secret-bearing output stayed visible. The redactor now redacts recursively while preserving the value's exact structure: strings redacted in place, arrays/objects keep their keys, non-string leaves (numbers, booleans, null) pass through untouched, and an unchanged response emits no rewrite at all.CR-02 — strict mode was a false promise, twice. (a) The shell wrapper ran
node "$MJS"then unconditionallyexit 0, erasing the strict-mode exit 2 before Claude ever saw it — it now propagates the child's exit status. (b) Comments and docs claimedFORGE_GUARD_STRICT=1"makes degradation blocking" — PostToolUse fires after the tool already ran and cannot block; all wording now states exit 2 is surfaced stderr feedback, with blocking belonging to the PreToolUse guard.ME-24 — honest positioning. README no longer claims "one brain for every AI coding agent", "enforced guardrails", or "every task passes a fast, deterministic gate"; automatic hooks are described as Claude Code-specific and advisory by default (enforcement opt-in via
FORGE_ENFORCE=1), and guardrails as defence in depth, not a security sandbox. The GUIDE'sFORGE_GUARD_STRICTrow states the visibility-not-blocking semantics.Checklist
npm testpasses (984 tests, 0 fail — 5 new: Bash-shaped object, Grep-shaped nested response, clean-object no-op, and two wrapper-level strict-mode tests driving the realsecret-redact.sh)npm run checkpasses (Biome)redactValuecovered via the guard's structured-response tests)security:)CHANGELOG.mdupdated under## [Unreleased]forge docs checkgreen)Risk & rollback
Extra checks (tick if applicable)
npm run typecheckpassestest/_fixtures.jshelpers)🤖 Generated with Claude Code
https://claude.ai/code/session_01KfCEnSJzSG914yyVesjjD6
Generated by Claude Code